/*
 * Copyright © 2011 by Rob Cash
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 * BasePlugInManager.java
 *
 * Created on Jun 25, 2011 at 11:44:35 AM
 */
package org.robcash.commons.plugin;

import java.lang.reflect.ParameterizedType;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Base class for plug-in managers
 * @author Rob Cash
 * @param <P> Type of plug-ins that can be managed
 */
public abstract class BasePlugInManager<P extends PlugIn> implements PlugInManager<P>
{
	@SuppressWarnings("unused")
	private static final Logger LOG = LoggerFactory.getLogger(BasePlugInManager.class);

	private final Set<P> plugIns;
	protected final Class<P> plugInBaseClass;

	/**
	 * Create a new plug-in manager
	 */
	@SuppressWarnings("unchecked")
	protected BasePlugInManager()
	{
		plugIns = new HashSet<P>();
		this.plugInBaseClass = (Class<P>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
	}

	/**
	 * {@inheritDoc}
	 * @throws PlugInException
	 */
	@Override
	public boolean registerPlugIn(final P plugIn) throws InvalidPlugInException, PlugInException
	{
		boolean registered = false;
		if ( validatePlugIn(plugIn) )
		{
			registered = plugIns.add(plugIn);
			if (registered)
			{
				plugIn.onRegister();
			}
		}

		return registered;
	}

	/**
	 * {@inheritDoc}
	 * @throws PlugInException
	 */
	@Override
	public boolean unregisterPlugIn(final P plugIn) throws PlugInException
	{
		boolean unregistered = plugIns.remove(plugIn);
		if (plugIn != null && unregistered)
		{
			plugIn.onUnregister();
		}

		return unregistered;
	}

	/**
	 * Validate a plug-in.
	 * @param plugIn Plug-in to validate
	 * @return {@code true} is returned if the plug-in is valid; {@code false}
	 * is returned if the plug-in is not valid. This implementation always
	 * returns {@code true}
	 * @throws InvalidPlugInException This can be thrown if the plug-in is not
	 * valid, instead of returning {@code false}. This implementation never
	 * throws an exception.
	 */
	protected boolean validatePlugIn(final P plugIn) throws InvalidPlugInException
	{
		return true;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Collection<P> getPlugIns()
	{
		return plugIns;
	}

}
